import 'package:sow_app_core/sow_app_core.dart';
import 'package:sow_app_core/src/usecase/subscribe_usecase.dart';
import 'package:sow_app_i18n/sow_app_i18n.dart';

import 'usecase.dart';

class GetNovelListUseCase
    extends UseCase<Future<List<Novel>>, GetNovelListParams> {
  final NovelRepository repository;

  GetNovelListUseCase(this.repository);
  @override
  Future<List<Novel>> call(params) async {
    final result = await repository.novelList(params.title);
    return result;
  }
}

class GetNovelListParams {
  final String? title;
  final int? channelId;
  final String? isAsc;
  final String? orderByColumn;

  GetNovelListParams(
      this.title, this.channelId, this.isAsc, this.orderByColumn);
}

class GetNovelDetailUseCase extends UseCase<Future<Novel>, String> {
  final NovelRepository repository;

  GetNovelDetailUseCase(this.repository);
  @override
  Future<Novel> call(params) async {
    final result = await repository.novelDetail(params);
    await repository.addVisitCount(params);
    return result;
  }
}

class IncreaseReadUseCase extends UseCase<void, String> {
  final NovelRepository repository;

  IncreaseReadUseCase(this.repository);
  @override
  Future<void> call(String params) => repository.novelRead(params);
}

class GetNovelChapterListUseCase
    extends UseCase<Future<List<Chapter>>, String> {
  final NovelRepository repository;

  GetNovelChapterListUseCase(this.repository);
  @override
  Future<List<Chapter>> call(String params) async =>
      (await repository.getChapterList(params)).toList();
}

class GetNovelChapterContentUseCase extends UseCase<Future<Chapter>, Chapter> {
  final NovelRepository repository;

  GetNovelChapterContentUseCase(this.repository);
  @override
  Future<Chapter> call(Chapter params) async {
    final chapter = (await repository.getChapterContent(
        params.novelId!, params.chapterId!));
    return Chapter(
        chapterId: chapter.chapterId,
        novelId: chapter.novelId,
        catalogue: chapter.catalogue,
        title: params.title,
        content: chapter.content);
  }
}

class NovelDetailGetChapterList extends UseCase<void, NoParams> {
  final NovelDetailPresenter _presenter;
  final NovelRepository _novelRepository;

  NovelDetailGetChapterList(this._presenter, this._novelRepository);
  @override
  void call(NoParams params) async {
    _presenter.novel =
        await GetNovelDetailUseCase(_novelRepository)(_presenter.novelId);
    _presenter.chapterList =
        await GetNovelChapterListUseCase(_novelRepository)(_presenter.novelId);
    _presenter.commentList =
        await GetNovelCommentListUseCase(_novelRepository)(_presenter.novelId);
    _presenter.inShelf = await NovelDetailIsNovelSubscribedUseCase(
        _novelRepository)(_presenter.novelId);
    _presenter.onComplete();
  }
}

class GetNovelCommentListUseCase
    extends UseCase<Future<List<NovelComment>>, String> {
  final NovelRepository _novelRepository;

  GetNovelCommentListUseCase(this._novelRepository);
  @override
  Future<List<NovelComment>> call(String params) {
    return _novelRepository.getBookCommentList(params);
  }
}

class AddNovelCommentUseCase extends UseCase<Future<void>, NovelComment> {
  final NovelRepository _novelRepository;

  AddNovelCommentUseCase(this._novelRepository);
  @override
  Future<void> call(NovelComment params) {
    return _novelRepository.addBookComment(params);
  }
}

class HomeGetBookShelf extends UseCase<Future<void>, NoParams> {
  final HomePresenter _presenter;
  final NovelRepository _novelRepository;

  HomeGetBookShelf(this._presenter, this._novelRepository);
  @override
  Future<void> call(NoParams params) async {
    _presenter.bookshelf = await _novelRepository.getBookShelf();
    _presenter.onComplete();
  }
}

class HomeGetReadHistory extends UseCase<Future<void>, NoParams> {
  final HomePresenter _presenter;
  final NovelRepository _novelRepository;

  HomeGetReadHistory(this._presenter, this._novelRepository);
  @override
  Future<void> call(NoParams params) async {
    _presenter.history = await _novelRepository.getReadHistory();
    _presenter.onComplete();
  }
}

class NovelDetailSubscribeUseCase extends UseCase<Future<void>, NoParams> {
  final NovelDetailPresenter _presenter;
  final NovelRepository _novelRepository;

  NovelDetailSubscribeUseCase(this._presenter, this._novelRepository);
  @override
  Future<void> call(NoParams params) async {
    if (await NovelDetailIsNovelSubscribedUseCase(_novelRepository)(
        _presenter.novelId)) {
      await UnsubscribeNovelUseCase(_novelRepository)(_presenter.novelId);
      _presenter.inShelf = false;
    } else {
      await SubscribeNovelUseCase(_novelRepository)(_presenter.novelId);
      _presenter.inShelf = true;
    }
    _presenter.onComplete();
  }
}

class NovelDetailIsNovelSubscribedUseCase
    extends UseCase<Future<bool>, String> {
  final NovelRepository _novelRepository;

  NovelDetailIsNovelSubscribedUseCase(this._novelRepository);
  @override
  Future<bool> call(String params) => _novelRepository.novelIsSubscribe(params);
}

class TagNovelGetNovelList extends UseCase<Future<void>, String> {
  final TagNovelPresenter _presenter;
  final NovelRepository _novelRepository;

  TagNovelGetNovelList(this._presenter, this._novelRepository);
  @override
  Future<void> call(String params) async {
    final String? bookStatusType = _presenter.bookStatusType == null
        ? null
        : _presenter.bookStatusType == 1
            ? '0'
            : '1';
    final String? sortType = _presenter.sortType == null
        ? null
        : _presenter.sortType == 1
            ? 'hot'
            : _presenter.sortType == 2
                ? 'new'
                : 'score';
    final String? wordCountMaxType = _presenter.wordCountType == null
        ? null
        : _presenter.wordCountType == 1
            ? '1000000'
            : _presenter.wordCountType == 2
                ? '3000000'
                : '99999999';
    final String? wordCountMinType = _presenter.wordCountType == null
        ? null
        : _presenter.wordCountType == 1
            ? '0'
            : _presenter.wordCountType == 2
                ? '1000000'
                : '3000000';
    _presenter.novelList = await _novelRepository.getNovelListByClass(params,
        bookStatus: bookStatusType,
        wordCountMax: wordCountMaxType,
        wordCountMin: wordCountMinType,
        sort: sortType);
    _presenter.onComplete();
  }
}

class ClassifyGetClassifyList extends UseCase<Future<void>, NoParams> {
  final ClassifyPresenter _presenter;
  final NovelRepository _novelRepository;

  ClassifyGetClassifyList(this._presenter, this._novelRepository);
  @override
  Future<void> call(NoParams params) async {
    _presenter.allClassifyOptions[WorkDirection.boy] = [
      ...(await _novelRepository.getHotClassifyList(
          workDirection: WorkDirection.boy)),
      ...(await _novelRepository.getClassifyList(
          workDirection: WorkDirection.boy, novelTagType: NovelTagType.theme)),
      ...(await _novelRepository.getClassifyList(
          workDirection: WorkDirection.boy,
          novelTagType: NovelTagType.character)),
      ...(await _novelRepository.getClassifyList(
          workDirection: WorkDirection.boy, novelTagType: NovelTagType.story))
    ];
    _presenter.allClassifyOptions[WorkDirection.girl] = [
      ...(await _novelRepository.getHotClassifyList(
          workDirection: WorkDirection.girl)),
      ...(await _novelRepository.getClassifyList(
          workDirection: WorkDirection.girl, novelTagType: NovelTagType.theme)),
      ...(await _novelRepository.getClassifyList(
          workDirection: WorkDirection.girl,
          novelTagType: NovelTagType.character)),
      ...(await _novelRepository.getClassifyList(
          workDirection: WorkDirection.girl, novelTagType: NovelTagType.story))
    ];
    _presenter.onComplete();
  }
}
